/*
策略模式（Strategy Pattern）是一种行为型设计模式，它允许在运行时选择算法的行为。
策略模式通过定义一系列算法，并将每个算法封装在独立的策略类中，使得它们可以互相替换。
这样，客户端可以根据需要选择不同的策略，而不需要修改客户端的代码。

在策略模式中，主要有三个角色：上下文（Context）、抽象策略（Strategy）和具体策略（Concrete Strategy）。

● 上下文（Context）是包含策略的对象。它维护一个对当前策略对象的引用，并将其行为委托给当前策略对象处理。上下文可以通过改变其当前策略对象来改变其行为。
● 抽象策略（Strategy）是定义策略的接口或抽象类。它定义了一个或多个抽象方法，用于处理上下文的请求。
● 具体策略（Concrete Strategy）是抽象策略的具体实现。它实现了抽象策略定义的方法，并根据需要改变上下文的行为。

使用策略模式的主要优点是将算法的实现与使用算法的客户端代码解耦，使得算法可以独立于客户端进行演化和变化。
同时，策略模式也符合开闭原则，因为可以通过增加新的具体策略类来扩展系统的行为。

下面是一个使用策略模式的C语言例程，该例程模拟了一个排序算法的选择：
*/

#include <stdio.h>
#include <stdlib.h>

// 抽象策略
typedef struct {
    void (*sort)(int arr[], int n);
} Strategy;

// 具体策略1：冒泡排序
void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

// 具体策略2：快速排序
void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pivot = arr[low];
        int i = low;
        int j = high;

        while (i < j) {
            while (i < j && arr[j] >= pivot) {
                j--;
            }
            arr[i] = arr[j];

            while (i < j && arr[i] <= pivot) {
                i++;
            }
            arr[j] = arr[i];
        }

        arr[i] = pivot;
        quickSort(arr, low, i - 1);
        quickSort(arr, i + 1, high);
    }
}

Strategy *createBubbleSortStrategy() {
    Strategy *strategy = (Strategy *)malloc(sizeof(Strategy));
    strategy->sort = bubbleSort;
    return strategy;
}

Strategy *createQuickSortStrategy() {
    Strategy *strategy = (Strategy *)malloc(sizeof(Strategy));
    strategy->sort = quickSort;
    return strategy;
}

void destroyStrategy(Strategy *strategy) {
    free(strategy);
}

// 上下文
typedef struct {
    Strategy *strategy;
} Context;

void setStrategy(Context *context, Strategy *strategy) {
    context->strategy = strategy;
}

void sortArray(Context *context, int arr[], int n) {
    context->strategy->sort(arr, n);
}

int main() {
    Context *context = (Context *)malloc(sizeof(Context));
    context->strategy = createBubbleSortStrategy();

    int arr1[] = {5, 2, 9, 1, 3};
    int n1 = sizeof(arr1) / sizeof(arr1[0]);
    sortArray(context, arr1, n1);
    printf("Bubble Sort: ");
    for (int i = 0; i < n1; i++) {
        printf("%d ", arr1[i]);
    }
    printf("\n");

    int arr2[] = {5, 2, 9, 1, 3};
    int n2 = sizeof(arr2) / sizeof(arr2[0]);
    setStrategy(context, createQuickSortStrategy());
    sortArray(context, arr2, n2);
    printf("Quick Sort: ");
    for (int i = 0; i < n2; i++) {
        printf("%d ", arr2[i]);
    }
    printf("\n");

    destroyStrategy(context->strategy);
    free(context);

    return 0;
}

/*
在上面的例程中，首先定义了抽象策略接口Strategy，其中包含了排序方法。
然后，定义了具体策略1bubbleSort和具体策略2quickSort，它们分别实现了抽象策略的排序方法。
在createBubbleSortStrategy和createQuickSortStrategy函数中，创建了具体策略对象，并将排序方法设置为相应的函数。
接下来，定义了上下文Context，它包含了一个策略对象的引用。
在setStrategy函数中，设置了上下文的策略对象。
在sortArray函数中，将上下文的请求委托给当前策略对象处理。
最后，在main函数中，创建了上下文对象，并通过上下文对象调用了不同的策略进行排序。

通过使用策略模式，我们可以根据需要选择不同的策略进行排序，而不需要修改客户端的代码。
策略模式使得算法的实现与使用算法的客户端代码解耦，使得系统更加灵活和可扩展。
*/